<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<div class="slideout-sidebar">
    <img class="info-icon" src="../../assets/images/scene_graph_icon.png"/>
    <h1>Scene Graph</h1>
    <h2>Scene graph with RTC coordinates and section planes</h2>
    <p>In this example, we're programmatically building a simple model from xeokit's scene graph components, while
        providing
        geometry vertex positions as relative-to-center (RTC) coordinates. We're also slicing the objects with a section
        plane.</p>
    <p>RTC coordinates are xeokit's mechanism for emulating full precision without the overhead of storing 64-bit
        values.</p>
    <h3>Components Used</h3>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/nodes/Node.js~Node.html"
               target="_other">Node</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/mesh/Mesh.js~Mesh.html"
               target="_other">Mesh</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/materials/PhongMaterial.js~PhongMaterial.html"
               target="_other">PhongMaterial</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/geometry/ReadableGeometry.js~ReadableGeometry.html"
               target="_other">ReadableGeometry</a>
        </li>
        <li>
            <a href="../../docs/function/index.html#static-function-buildBoxGeometry"
               target="_other">buildBoxGeometry</a>
        </li>
    </ul>
</div>
</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {
        Viewer,
        Mesh,
        Node,
        PhongMaterial,
        buildBoxGeometry,
        ReadableGeometry,
        math,
        SectionPlanesPlugin
    } from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer and arrange the camera
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true,
        numCachedSectionPlanes: 4
    });

    viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
    viewer.scene.camera.look = [0, -5.75, 0];
    viewer.scene.camera.up = [0.37, 0.91, -0.11];

    const cameraControl = viewer.cameraControl;
    cameraControl.navMode = "orbit";
    cameraControl.followPointer = true;

    //-----------------------------------------------------------
    // Create several origin points
    //-----------------------------------------------------------

    //const OFFSET = 1000000000.0;
    const OFFSET = 40.0;

    const origins = [
        [0, 0, 0],
        [OFFSET, 0, 0],
        [0, 0, OFFSET],
        [OFFSET, 0, OFFSET]
    ];

    //-----------------------------------------------------------
    // Create a simple table model
    // at each of our origins. This will result in several
    // tables, positioned apart from each other.
    //-----------------------------------------------------------

    for (let i = 0, len = origins.length; i < len; i++) {
        buildTable(origins[i]);
    }

    viewer.cameraFlight.jumpTo(viewer.scene);

    //------------------------------------------------------------------------------------------------------------------
    // Create a moving SectionPlane, that moves through the table models
    //------------------------------------------------------------------------------------------------------------------

    const sectionPlanes = new SectionPlanesPlugin(viewer, {
        overviewCanvasId: "mySectionPlanesOverviewCanvas",
        overviewVisible: true
    });

    //const origin = origins[2];

    const sectionPlane = sectionPlanes.createSectionPlane({
        id: "mySectionPlane",
        pos: [origins[0][0] - 10, -10, origins[0][2] - 10],
        dir: math.normalizeVec3([1.0, 0.01, 1])
    });

    sectionPlanes.showControl(sectionPlane.id);

    let i = 0;
    viewer.scene.on("tick", () => {
        sectionPlane.pos = [sectionPlane.pos[0] + i, sectionPlane.pos[1], sectionPlane.pos[2] + i];
        i += 0.001;
    });

    //------------------------------------------------------------------------------------------------------------------
    // Mouse over Entities to highlight them
    //------------------------------------------------------------------------------------------------------------------

    var lastPickedEntity = null;

    viewer.scene.input.on("mousemove", function (coords) {

        var hit = viewer.scene.pick({
            canvasPos: coords
        });

        if (hit) {

            if (!lastPickedEntity || hit.entity.id !== lastPickedEntity.id) {
                if (lastPickedEntity) {
                    lastPickedEntity.highlighted = false;
                }
                lastPickedEntity = hit.entity;
                hit.entity.highlighted = true;
            }
        } else {
            if (lastPickedEntity) {
                lastPickedEntity.highlighted = false;
                lastPickedEntity = null;
            }
        }
    });

    //------------------------------------------------------------------------------------------------------------------
    // Flies camera to the specified origin
    //------------------------------------------------------------------------------------------------------------------

    window.gotoRTCCenter = function (i) {

        const origin = origins[i];

        if (!origin) {
            return;
        }

        viewer.cameraFlight.flyTo({
            eye: [origin[0], 0, origin[2] - 10],
            look: origin,
            up: [0, 1, 0]
        });
    };

    //------------------------------------------------------------------------------------------------------------------
    // Creates a simple table-shaped model from Nodes and Meshes, and centered at the given origin
    //------------------------------------------------------------------------------------------------------------------

    function buildTable(origin) {

        let modelId = math.createUUID();

        const boxGeometry = new ReadableGeometry(viewer.scene, buildBoxGeometry({
            xSize: 1,
            ySize: 1,
            zSize: 1
        }));

        const sceneModel = new Node(viewer.scene, {
            id: modelId,
            isModel: true, // <--------------------- Node represents a model
            rotation: [0, 0, 0],
            position: [0, 0, 0],
            scale: [1, 1, 1],
            edges: true,

            children: [

                new Mesh(viewer.scene, { // Red table leg
                    isObject: true, // <---------- Node represents an object
                    origin: origin, // <---- This mesh's positions and transforms are relative to the origin
                    position: [-4, -6, -4],
                    scale: [1, 3, 1],
                    rotation: [0, 0, 0],
                    geometry: boxGeometry,
                    material: new PhongMaterial(viewer.scene, {
                        diffuse: [1, 0.3, 0.3]
                    })
                }),

                new Mesh(viewer.scene, { // Green table leg
                    isObject: true, // <---------- Node represents an object
                    origin: origin, // <---- This mesh's positions and transforms are relative to the origin
                    position: [4, -6, -4],
                    scale: [1, 3, 1],
                    rotation: [0, 0, 0],
                    geometry: boxGeometry,
                    material: new PhongMaterial(viewer.scene, {
                        diffuse: [0.3, 1.0, 0.3]
                    })
                }),

                new Mesh(viewer.scene, {// Blue table leg
                    isObject: true, // <---------- Node represents an object
                    origin: origin, // <---- This mesh's positions and transforms are relative to the origin
                    position: [4, -6, 4],
                    scale: [1, 3, 1],
                    rotation: [0, 0, 0],
                    geometry: boxGeometry,
                    material: new PhongMaterial(viewer.scene, {
                        diffuse: [0.3, 0.3, 1.0]
                    })
                }),

                new Mesh(viewer.scene, {  // Yellow table leg
                    isObject: true, // <---------- Node represents an object
                    origin: origin, // <---- This mesh's positions and transforms are relative to the origin
                    position: [-4, -6, 4],
                    scale: [1, 3, 1],
                    rotation: [0, 0, 0],
                    geometry: boxGeometry,
                    material: new PhongMaterial(viewer.scene, {
                        diffuse: [1.0, 1.0, 0.0]
                    })
                }),

                new Mesh(viewer.scene, { // Purple table top
                    isObject: true, // <---------- Node represents an object
                    origin: origin, // <---- This mesh's positions and transforms are relative to the origin
                    position: [0, -3, 0],
                    scale: [6, 0.5, 6],
                    rotation: [0, 0, 0],
                    geometry: boxGeometry,
                    material: new PhongMaterial(viewer.scene, {
                        diffuse: [1.0, 0.3, 1.0]
                    })
                })
            ]
        });

        sceneModel.edges = true;
    }

</script>
</html>